'basewidget.bas

#include once "mud-gui/widgets/basewidget.bi"
#include once "mud-gui/util.bi"
#ifndef false
#define false 0
#endif
#ifndef true
#define true not false
#endif
namespace ui

destructor Signal_list( )
	if _next <> 0 then delete _next
end destructor

property BaseWidget.setClicked( byval func as signal_callback )
	addRemoveSignal( func, gevent.leftclick )
end property

property BaseWidget.setMouseOver( byval func as signal_callback )
	addRemoveSignal( func, gevent.mousemove )
end property

property BaseWidget.setMouseDown( byval func as signal_callback )
	addRemoveSignal( func, gevent.mousedown )
end property

property BaseWidget.setMouseWheel( byval func as signal_callback )
	addRemoveSignal( func, gevent.wheel )
end property

property BaseWidget.setKeyStroke( byval func as signal_callback )
	addRemoveSignal( func, gevent.keystroke )
end property

property BaseWidget.setDestroy( byval func as signal_callback )
	addRemoveSignal( func, gevent.destroy )
end property

property BaseWidget.setTimerExpire( byval func as signal_callback )
	addRemoveSignal( func, gevent.time_e )
end property

property BaseWidget.setResize( byval func as signal_callback )
	addRemoveSignal( func, gevent.resize )
end property

property BaseWidget.setRepaint( byval func as signal_callback )
	addRemoveSignal( func, gevent.repaint )
end property

property BaseWidget.setUserSignal( byval func as signal_callback )
	addRemoveSignal( func, gevent.user )
end property

sub BaseWidget.addRemoveSignal( byval func as signal_callback, byval s as GEVENT )

	var found = false
	var tmp = @_signals
	
	while (*tmp <> 0) andalso (found = false)

		with (*tmp)->_sig
		select case s
			case gevent.mousemove
				if .mouseover = func then
					.mouseover = 0
					found = true
				elseif .mouseover = 0 then
					.mouseover = func
					found = true
				end if
			case gevent.mousedown
				if .mousedown = func then
					.mousedown = 0
					found = true
				elseif .mousedown = 0 then
					.mousedown = func
					found = true
				end if
			case gevent.leftclick to gevent.middleclick
				if .clicked = func then
					.clicked = 0
					found = true
				elseif .clicked = 0 then
					.clicked = func
					found = true
				end if
			case gevent.wheel
				if .mousewheel = func then
					.mousewheel = 0
					found = true
				elseif .mousewheel = 0 then
					.mousewheel = func
					found = true
				end if
			case gevent.keystroke
				if .keystroke = func then
					.keystroke = 0
					found = true
				elseif .keystroke = 0 then
					.keystroke = func
					found = true
				end if
			case gevent.time_e
				if .timerExpire = func then
					.timerExpire = 0
					found = true
				elseif .timerExpire = 0 then
					.timerExpire = func
					found = true
				end if
			case gevent.repaint
				if .repaint = func then
					.repaint = 0
					found = true
				elseif .repaint = 0 then
					.repaint = func
					found = true
				end if
			case gevent.resize
				if .resize = func then
					.resize = 0
					found = true
				elseif .resize = 0 then
					.resize = func
					found = true
				end if
			case gevent.destroy
				if .destroy = func then
					.destroy = 0
					found = true
				elseif .destroy = 0 then
					.destroy = func
					found = true
				end if
			case else
				if .usersignal = func then
					.usersignal = 0
					found = true
				elseif .usersignal = 0 then
					.usersignal = func
					found = true
				end if
		end select
		end with

		tmp = @(*tmp)->_next

	wend

		if found = false then
					*tmp = new Signal_list
					with (*tmp)->_sig
					select case s
					case gevent.mousemove
						.mouseover = func
					case gevent.mousedown
						.mousedown = func
					case gevent.leftclick to gevent.middleclick
						.clicked = func
					case gevent.wheel
						.mousewheel = func
					case gevent.keystroke
						.keystroke = func
					case gevent.time_e
						.timerExpire = func
					case gevent.repaint
						.repaint = func
					case gevent.resize
						.resize = func
					case gevent.destroy
						.destroy = func
					case else
						.usersignal = func
					end select
				end with
				
		end if

end sub

function BaseWidget.process_signals( byval ref as BaseWidget ptr, byval e as _GUI_EVENT_ ptr ) as integer

	if _signals = 0 then return 0
        var ret = 0
	var tmp = _signals
	while 1
		if tmp = 0 then exit while
		with tmp->_sig
		select case e->id
			case gevent.mousemove
				if .mouseover <> 0 then ret = .mouseover( ref, e )
			case gevent.mousedown
				if .mousedown <> 0 then ret = .mousedown( ref, e )
			case gevent.leftclick to gevent.middleclick
				if .clicked <> 0 then ret = .clicked( ref, e )
			case gevent.wheel
				if .mousewheel <> 0 then ret = .mousewheel( ref, e )
			case gevent.keystroke
				if .keystroke <> 0 then ret = .keystroke( ref, e )
			case gevent.time_e
				if .timerExpire <> 0 then ret = .timerExpire( ref, e )
			case gevent.repaint
				if .repaint <> 0 then ret = .repaint( ref, e )
			case gevent.resize
				if .resize <> 0 then ret = .resize( ref, e )
			case gevent.destroy
				if .destroy <> 0 then ret = .destroy( ref, e )
			case else
				if .usersignal <> 0 then  ret = .usersignal( ref, e )
		end select
		end with
		tmp = tmp->_next
		if ret <> 0 then return ret
	wend

	return 0

end function

function BaseWidget.hasChild( byval _child_ as BaseWidget ptr ) as integer

	if children = 0 then return 0

	var tmp = children
	while 1
		if tmp = 0 then exit while
		if tmp->_data = _child_ then return 1
		tmp = tmp->_next
	wend

	return 0

end function

sub BaseWidget.deleteChild( byval _child_ as BaseWidget ptr )

	if children = 0 then return

	var tmp = children
	var old = tmp
	while 1
		if tmp = 0 then exit while
		if tmp->_data = _child_ then
			var new_ = tmp->_next
			old->_next = new_
			delete tmp
			return
		end if
		old = tmp
		tmp = tmp->_next
	wend

end sub

sub BaseWidget.addChild( byval _child_ as BaseWidget ptr )

	if children = 0 then
		children = new BaseWidget_list
		children->_data = _child_
		children->_next = 0
	else
		var tmp = children
		while tmp->_next <> 0
			tmp = tmp->_next
		wend
		tmp->_next = new BaseWidget_list
		tmp = tmp->_next
		tmp->_data = _child_
		tmp->_next = 0
	end if

	_child_->Parent = @this

end sub

function BaseWidget.process_event( byval ref as BaseWidget ptr, byval e as _GUI_EVENT_ ptr ) as integer

	process_signals( ref, e )
	var ret = 0

	var tmp = ref->children
	while 1
		if tmp = 0 then exit while
		if e->id < gevent.keystroke then
			if boundingBox(tmp->_data->x,tmp->_data->y,tmp->_data->width,tmp->_data->height,e->m_x,e->m_y) = 1 then
				ret = tmp->_data->process_event( tmp->_data, e )
			end if
		else
			ret = tmp->_data->process_event( tmp->_data, e )
		end if
		tmp = tmp->_next
		if ret <> 0 then return ret
	wend

	return 0

end function

destructor BaseWidget( )
	var e = new _GUI_EVENT_
	e->id = gevent.destroy
	process_event( @this, e )

	delete e
	if this.buffer <> 0 then imagedestroy( this.buffer )
	if children <> 0 then
		delete children
		children = 0
	end if
	if _signals <> 0 then delete _signals
end destructor

destructor BaseWidget_list( )
	if _data <> 0 then delete cast(BaseWidget ptr, _data)
	_data = 0
	if _next <> 0 then delete _next
	_next = 0
end destructor

end namespace
